package com.leo.springboot.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.leo.springboot.common.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

import com.leo.springboot.service.IFileService;
import com.leo.springboot.entity.Files;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author leo
 * @since 2022-07-01
 */
@RestController
@CrossOrigin
@RequestMapping("/file")
public class FilesController {

    @Value("${files.upload.path}")
    private String filePath;
    @Resource
    private IFileService fileService;

    @PostMapping("/save")
    public Result save(@RequestBody Files file) {
        return Result.success(fileService.saveOrUpdate(file), "更新成功！");
    }

    @DeleteMapping("/del/{id}")
    public Result delete(@PathVariable Integer id) {
        Files file = fileService.getById(id);
        file.setIsDelete(true);
        return Result.success(fileService.saveOrUpdate(file), "删除成功");
    }

    @PostMapping("/del/batch")
    public Result deleteBatch(@RequestBody List<Integer> ids) {
        QueryWrapper<Files> filesQueryWrapper = new QueryWrapper<>();
        filesQueryWrapper.in("id", ids);
        List<Files> list = fileService.list(filesQueryWrapper);
        for (Files file : list) {
            file.setIsDelete(true);
        }
        return Result.success(fileService.saveOrUpdateBatch(list), "批量删除成功！");
    }

    @GetMapping
    public List<Files> findAll() {
        return fileService.list();
    }

    @GetMapping("/{id}")
    public Files findOne(@PathVariable Integer id) {
        return fileService.getById(id);
    }

    @GetMapping("/page")
    public Page<Files> findPage(@RequestParam Integer pageNum,
                                @RequestParam Integer pageSize,
                                @RequestParam(defaultValue = "") String filename) {
        QueryWrapper<Files> wrapper = new QueryWrapper<>();
        wrapper.eq("is_Delete", false);
        wrapper.like("name", filename);
        wrapper.orderByDesc("id");
        return fileService.page(new Page<>(pageNum, pageSize), wrapper);
    }

    @PostMapping("/upload")
    public String upload(@RequestParam MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String type = FileUtil.extName(originalFilename);
        long size = file.getSize() / 1024;
        //获取UUID值
        String uuid = IdUtil.fastSimpleUUID();
        String fileUUID = uuid + StrUtil.DOT + type;
        String url;
        //创建文件流(在指定的目录下)
        File uploadFile = new File(filePath + fileUUID);
        //创建文件的md5值，避免相同文件占用空间
        String md5 = SecureUtil.md5(file.getInputStream());
        // 判断配置的文件目录是否存在，若不存在则创建一个新的文件目录
        File parentFile = uploadFile.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        //转存前先判断数据库中有没有相同的md5值的文件，若有，则不需要转存到磁盘中，直接将数据库中存在的url作为当前类的url
        QueryWrapper<Files> filesQueryWrapper = new QueryWrapper<>();
        filesQueryWrapper.eq("md5", md5);
        Files one = getFileByMd5(md5);
        if (one != null) {
            url = one.getUrl();
        } else {
            url = "http://localhost:8080/file/download/" + fileUUID;
            //将前端传来的文件转存到磁盘
            file.transferTo(uploadFile);
        }

        Files files = new Files();
        files.setName(originalFilename);
        files.setType(type);
        files.setSize(size);
        files.setUrl(url);
        files.setMd5(md5);
        fileService.save(files);
        return url;
    }

    /**
     * 文件下载接口   http://localhost:8080/file/{fileUUID}
     *
     * @param fileUUID
     * @param response
     * @throws IOException
     */
    @GetMapping("/download/{fileUUID}")
    public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        // 根据文件的唯一标识码获取文件
        File uploadFile = new File(filePath + fileUUID);
        // 设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
        response.setContentType("application/octet-stream");

        // 读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    private Files getFileByMd5(String md5) {
        // 查询文件的md5是否存在
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        List<Files> filesList = fileService.list(queryWrapper);
        return filesList.size() == 0 ? null : filesList.get(0);
    }
}

